iT邦幫忙

2021 iThome 鐵人賽

DAY 5
2
Modern Web

ASP.NET Web Forms 入門 - 30天建立遊艇網頁專案後端及後台功能 C#系列 第 5

Day 5 - Using Argon2 for Password Verifying with ASP.NET Web Forms C# 使用 Argon2 驗證密碼

  • 分享至 

  • xImage
  •  

=x= 🌵 Sign In page 後台登入密碼驗證。


驗證流程介紹 :

https://ithelp.ithome.com.tw/upload/images/20210918/20139487OimBuuOXjf.jpg

📌 使用者於登入頁面輸入帳號及密碼送出後,後端會依取得帳號連進資料庫比對,如果帳號不存在,就送出帳號不存在的說明,如果帳號存在,就取出該帳號 "密碼加鹽加密結果" + "鹽的內容",再將取出的 "鹽的內容" 與登入頁輸入的密碼又一次進行 hash 雜湊加密,最後將加密後的結果比對資料庫取出的 "密碼加鹽加密結果",如果比對不相同,就送出密碼錯誤的說明,如果比對相同就進行跳轉頁面,登入成功。



Sign In page - Argon2 驗證實作 :

🧠 密碼如果驗證成功會一併發出 FormsAuthenticationTicket 驗證票,驗證票可用來進行權限的識別導引,以及再後台操作時保持登入狀態,以下程式碼會一併呈現使用方式。

👀 驗證與授權必讀好文1 : 簡介 ASP.NET 表單驗證 (FormsAuthentication) 的運作方式

👀 驗證與授權必讀好文2 : [ASP.NET] Forms 驗證與授權

1. 在 Web.config 的增加使用表單驗證設定如下

<configuration>
  <system.web>
        <authentication mode="Forms"></authentication>
  </system.web>
</configuration>


2. 於登入頁後置程式碼加入驗證功能

// Argon2 驗證加密密碼
// Hash 處理加鹽的密碼功能
private byte[] HashPassword(string password, byte[] salt)
{
    var argon2 = new Argon2id(Encoding.UTF8.GetBytes(password));

    //底下這些數字會影響運算時間,而且驗證時要用一樣的值
    argon2.Salt = salt;
    argon2.DegreeOfParallelism = 8; // 4 核心就設成 8
    argon2.Iterations = 4; //迭代運算次數
    argon2.MemorySize = 1024 * 1024; // 1 GB

    return argon2.GetBytes(16);
}
//驗證
private bool VerifyHash(string password, byte[] salt, byte[] hash)
{
    var newHash = HashPassword(password, salt);
    return hash.SequenceEqual(newHash); // LINEQ
}


3. 設定 Cookie 驗證票方法

//設定驗證票
private void SetAuthenTicket(string userData, string userId)
{
    //宣告一個驗證票 //需額外引入 using System.Web.Security;
    FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, userId, DateTime.Now, DateTime.Now.AddHours(3), false, userData);
    //加密驗證票
    string encryptedTicket = FormsAuthentication.Encrypt(ticket);
    //建立 Cookie
    HttpCookie authenticationCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
    //將 Cookie 寫入回應
    Response.Cookies.Add(authenticationCookie);
}
  • 🌵 驗證票的AddHours要配合使用情境設定,使用者切換頁面時可以保持登入狀態。

4. 在登入頁送出按鈕 Click 事件加入以下程式碼

protected void Button1_Click(object sender, EventArgs e)
{
    string password = TextBox2.Text;

    // 1.連線資料庫
    SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
    // 2.sql語法 (@參數化避免隱碼攻擊)
    string sql = "SELECT * FROM managerData WHERE account = @account";
    // 3.創建 command 物件
    SqlCommand command = new SqlCommand(sql, connection);
    // 4.放入參數化資料
    command.Parameters.AddWithValue("@account", TextBox1.Text);
    // 5.資料庫用 Adapter 執行指令
    SqlDataAdapter dataAdapter = new SqlDataAdapter(command);
    // 6.建立一個空的 Table
    DataTable dataTable = new DataTable();
    // 7.將資料放入 Table
    dataAdapter.Fill(dataTable);
    // 登入流程管理 (Cookie)
    if (dataTable.Rows.Count > 0) {
        // SQL 有找到資料時執行

        //將字串轉回 byte
        byte[] hash = Convert.FromBase64String(dataTable.Rows[0]["password"].ToString());
        byte[] salt = Convert.FromBase64String(dataTable.Rows[0]["salt"].ToString());
        //驗證密碼
        bool success = VerifyHash(password, salt, hash);

        if (success) {
            //宣告驗證票要夾帶的資料 (用;區隔)
            string userData = dataTable.Rows[0]["maxPower"].ToString() + ";" + dataTable.Rows[0]["account"].ToString() + ";" + dataTable.Rows[0]["name"].ToString() + ";" + dataTable.Rows[0]["email"].ToString();
            //設定驗證票(夾帶資料,cookie 命名) // 需額外引入using System.Web.Configuration;
            SetAuthenTicket(userData, TextBox1.Text);
            //導頁至權限分流頁
            Response.Redirect("CheckAccount.ashx");
        }
        else {
            //資料庫裡找不到相同資料時,表示密碼有誤!
            Label4.Text = "password error, login failed!";
            Label4.Visible = true;
            connection.Close();
            return;
        }
    }
    else {
        //資料庫裡找不到相同資料時,表示帳號有誤!
        Label4.Text = "Account error, login failed!";
        Label4.Visible = true;
        //終止程式
        //Response.End(); //會清空頁面
        return;
    }
        connection.Close();
}
  • 🌵 權限分流頁 "CheckAccount.ashx" 可先暫時替換成任一頁面進行測試。

5. 渲染網頁並輸入帳密驗證確認會不會實現上述功能,完成~



密碼驗證功能總結 :

📢 因為使用 Argon2 驗證會增加運算時間,跳轉頁面會有延遲,建議在 .aspx 頁面用 JavaScript 監聽按鈕加入驗證中的 CSS 蓋版動畫,另外登入頁可增加一按鈕當成返回前台首頁的功能,權限分流頁使用 .ashx (泛型處理常式)製作,在後續頁面會一併介紹相關設定及功能。

補充加胡椒 :

🧂 要使密碼更安全的作法,其實還要加"安全鹽"或稱作"胡椒",因為鹽會和加密後的密碼一起放在資料庫,如果資料庫被攻擊就可能會被破解,"胡椒"需要另外存放來達到提升安全性的效果,或是把它寫在程式裡,這樣至少也是放在不同地方。

👀 胡椒的使用方式 : How to apply a pepper correctly to bcrypt?

👀 胡椒的維基百科 : Pepper (cryptography)

  • 明日將介紹如何製作權限分流及清除頁面快取功能。

上一篇
Day 4 - Using Argon2 for Salted Password Hashing with ASP.NET Web Forms C# 使用 Argon2 替密碼加鹽後雜湊加密
下一篇
Day 6 - Using ASHX File for User Authorization Management with ASP.NET Web Forms C# 使用泛型處理常式進行權限分流
系列文
ASP.NET Web Forms 入門 - 30天建立遊艇網頁專案後端及後台功能 C#30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言